<?php
class wxxyx
{
    public function __construct($option)
    {
        $this->isProEnv  = $option['env'] == 0; //是否正式环境
        $this->mdsAppkey = $this->isProEnv ? $option['mdsAppkey'] : $option['mdsAppkeySandbox']; //米大师秘钥
        $this->appid     = $option['appid'];
        $this->appsecret = $option['appsecret'];
        $this->offerid   = $option['offerid'];
    }

    /**
     * 获取用户的openid和session_key
     * @param    [string]     $code [微信code]
     * @return   [array]            [返回openid和session_key]
     */
    public function getLoginInfo($code)
    {
        $post_url = "https://api.weixin.qq.com/sns/jscode2session?appid={$this->appid}&secret={$this->appsecret}&js_code={$code}&grant_type=authorization_code";

        $result = $this->httpRequest($post_url, '', 'GET');
        $result = json_decode($result, true);
        return $result;
    }

    /**
     * 查看某个用户的游戏币余额
     * @param    [string]     $params [所需参数]
     * @return   [array]              [用户余额]
     */
    public function midasGetBalance($params)
    {
        $accessToken = $this->getAccessToken();
        $post_uri    = $this->isProEnv ? '/cgi-bin/midas/getbalance' : '/cgi-bin/midas/sandbox/getbalance';

        $data = [
            'openid'   => $params['openid'],
            'appid'    => $this->appid,
            'offer_id' => $this->offerid,
            'ts'       => time(),
            'zone_id'  => $params['zoneid'],
            'pf'       => $params['platform'],
        ];

        $data['sig']          = $this->getSig($data, $post_uri, $this->mdsAppkey);
        $data['access_token'] = $accessToken;
        $data['mp_sig']       = $this->getSig($data, $post_uri, $this->mdsAppkey, $params['session_key']);
        $result               = $this->httpRequest("https://api.weixin.qq.com{$post_uri}?access_token={$accessToken}", json_encode($data));
        $result               = json_decode($result, true);
        return $result;
    }

    /**
     * 扣除某个用户的游戏币
     * @param    [string]     $params [所需参数]
     * @return   [array]              [支付结果]
     */
    public function midasPay($params)
    {
        $access_token = $this->getAccessToken();
        $post_uri     = $this->isProEnv ? '/cgi-bin/midas/pay' : '/cgi-bin/midas/sandbox/pay';

        $data = [
            'openid'   => $params['openid'],
            'appid'    => $this->appid,
            'offer_id' => $this->offerid,
            'ts'       => time(),
            'zone_id'  => $params['zoneid'],
            'pf'       => $params['platform'],
            'amt'      => $params['amt'],
            'bill_no'  => $params['orderNo'],
        ];
        $data['sig']          = $this->getSig($data, $post_uri, $this->mdsAppkey);
        $data['access_token'] = $access_token;
        $data['mp_sig']       = $this->getSig($data, $post_uri, $this->mdsAppkey, $params['session_key']);

        $result = $this->httpRequest("https://api.weixin.qq.com{$post_uri}?access_token={$access_token}", json_encode($data));
        $result = json_decode($result, true);

        return $result;
    }

    /**
     * 向某个用户赠送游戏币
     * @param    [string]     $params [所需参数]
     * @return   [array]              [赠送游戏币结果]
     */
    public function midasPresent($params)
    {
        $access_token = $this->getAccessToken();
        $post_uri     = $this->isProEnv ? '/cgi-bin/midas/present' : '/cgi-bin/midas/sandbox/present';

        $data = [
            'openid'         => $params['openid'],
            'appid'          => $this->appid,
            'offer_id'       => $this->offerid,
            'ts'             => time(),
            'zone_id'        => $params['zoneid'],
            'pf'             => $params['platform'],
            'present_counts' => $params['present_counts'],
            'bill_no'        => $params['bill_no'],
        ];
        $data['sig']          = $this->getSig($data, $post_uri, $this->mdsAppkey);
        $data['access_token'] = $access_token;
        $data['mp_sig']       = $this->getSig($data, $post_uri, $this->mdsAppkey, $params['session_key']);

        $result = $this->httpRequest("https://api.weixin.qq.com{$post_uri}?access_token={$access_token}", json_encode($data));
        $result = json_decode($result, true);

        return $result;
    }

    /**
     * 在有效期内的订单，可以通过本接口取消该笔扣除游戏币的订单
     * @param    [string]     $params [所需参数]
     * @return   [array]              [取消支付结果]
     */
    public function midasCancelPay($params)
    {
        $access_token = $this->getAccessToken();
        $post_uri     = $this->isProEnv ? '/cgi-bin/midas/cancelpay' : '/cgi-bin/midas/sandbox/cancelpay';

        $data = [
            'openid'   => $params['openid'],
            'appid'    => $this->appid,
            'offer_id' => $this->offerid,
            'ts'       => time(),
            'zone_id'  => $params['zoneid'],
            'pf'       => $params['platform'],
            'bill_no'  => $params['bill_no'],
        ];
        $data['sig']          = $this->getSig($data, $post_uri, $this->mdsAppkey);
        $data['access_token'] = $access_token;
        $data['mp_sig']       = $this->getSig($data, $post_uri, $this->mdsAppkey, $params['session_key']);

        $result = $this->httpRequest("https://api.weixin.qq.com{$post_uri}?access_token={$access_token}", json_encode($data));
        $result = json_decode($result, true);

        return $result;
    }

    /**
     * 获取access_token
     */
    public function getAccessToken()
    {
        if ($access_token = $this->getCache('access_token')) {
            return $access_token;
        }
        $result = $this->httpRequest("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appid}&secret={$this->appsecret}", '', 'GET');
        $result = json_decode($result, true);

        $this->setCache('access_token', $result['access_token'], $result['expires_in']);
        return $result['access_token'];
    }

    /**
     * 签名函数
     */
    protected function getSig($params, $org_loc, $key, $session_key = '')
    {
        ksort($params);
        $stringA = '';
        foreach ($params as $k => $v) {
            $stringA .= "{$k}={$v}&";
        }
        $stringA = substr($stringA, 0, -1);

        if ($session_key == '') {
            $stringSignTemp = $stringA . "&org_loc={$org_loc}&method=POST&secret={$key}";
            return hash_hmac("sha256", $stringSignTemp, $key);
        } else {
            $stringSignTemp = $stringA . "&org_loc={$org_loc}&method=POST&session_key={$session_key}";
            return hash_hmac("sha256", $stringSignTemp, $session_key);
        }
    }

    /**
     * 请求函数
     */
    public function httpRequest($url, $data, $method = 'POST', $header = array())
    {
        if (!$header) {
            $header = array('Content-type: application/x-www-form-urlencoded');
        }

        $req = curl_init();
        curl_setopt($req, CURLOPT_URL, $url);
        curl_setopt($req, CURLOPT_HTTPHEADER, $header);
        curl_setopt($req, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($req, CURLOPT_RETURNTRANSFER, true);

        if (substr($url, 0, 8) == 'https://') {
            curl_setopt($req, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($req, CURLOPT_SSL_VERIFYHOST, false);
        }

        curl_setopt($req, CURLOPT_POST, $method == 'POST' ? 1 : 0);
        curl_setopt($req, CURLOPT_POSTFIELDS, is_array($data) ? http_build_query($data) : $data);
        $data = curl_exec($req);
        curl_close($req);

        return !empty($data) ? $data : false;
    }
    /**
     * 设置缓存，按需重载
     * @param string $cachename
     * @param mixed $value
     * @param int $expired
     * @return boolean
     */
    protected function setCache($cachename, $value, $expired)
    {
        //TODO: set cache implementation
        return fanse;
    }

    /**
     * 获取缓存，按需重载
     * @param string $cachename
     * @return mixed
     */
    protected function getCache($cachename)
    {
        //TODO: get cache implementation
        return false;
    }
}

/******************使用方法******************/
$options = [
    'env'              => 1,//0是正式环境，1是测试环境
    'mdsAppkey'        => '',//正式环境的appkey
    'mdsAppkeySandbox' => '',//测试环境的appkey
    'appid'            => '',//appid
    'appsecret'        => '',//appsecret
    'offerid'          => '',//支付应用ID
];
$Wxxyx = new wxxyx($options);

//1、在小游戏端调用wx.login()获取code，传给服务端获取用户的openid和session_key
$res1  = $Wxxyx->getLoginInfo($_REQUEST['code']);

$openid      = $res1['openid'];
$session_key = $res1['session_key'];


//2、获取用户余额
$params = [
    'openid'      => $openid,
    'zoneid'      => 1,//后台填的分区id
    'platform'    => 'android', //小游戏暂只支持安卓
    'session_key' => $session_key,
];
$res2 = $Wxxyx->midasGetBalance($params);

//3、扣除某个用户的游戏币
$params = [
    'openid'      => $openid,
    'zoneid'      => 1,//后台填的分区id
    'platform'    => 'android',//小游戏暂只支持安卓
    'amt'         => 10,//扣除游戏币，注意人民币换算哦，也是后台配置的比例
    'orderNo'     => time(),//订单号
    'session_key' => $session_key,
];
$res3 = $Wxxyx->midasPay($params);

//4、赠送游戏币给某个用户
$params = [
    'openid'         => $openid,
    'zoneid'         => 1,//后台填的分区id
    'platform'       => 'android',//小游戏暂只支持安卓
    'present_counts' => 10,//赠送游戏币数量，注意人民币换算哦，也是后台配置的比例
    'bill_no'        => time(),//赠送订单号
    'session_key'    => $session_key,
];
$res4 = $Wxxyx->midasPresent($params);

//5、赠送游戏币给某个用户
$params = [
    'openid'      => $openid,
    'zoneid'      => 1,//后台填的分区id
    'platform'    => 'android',//小游戏暂只支持安卓
    'bill_no'     => time(),//取消支付的订单号
    'session_key' => $session_key,
];
$res5 = $Wxxyx->midasCancelPay($params);